﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Security.Permissions;

namespace RollDesktop
{
    public class RegistryKeyHelper
    {
        public RegistryKey MainKey { get; set; }
        public RegistryKey CurrentRegistryKey { get; set; }
        public RegistryKeyHelper()
        {
            MainKey = Registry.LocalMachine;
        }

        public RegistryKeyHelper(MainRegistryKey mainRegistryKey, string subKeyName, bool writable)
        {
            SetMainRegistryKey(mainRegistryKey);
            SetCurrentRegistryKey(subKeyName, true, writable);
        }

        /// <summary>
        /// 设置指定的名称和值
        /// </summary>
        /// <param name="subKey"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        private void SetValue(RegistryKey subKey, string name, string value, RegValueKind regValueKind)
        {
            subKey.SetValue(name, value, GetRegValueKind(regValueKind));
            subKey.Close();
        }

        /// <summary>
        /// 打开子节点
        /// </summary>
        /// <param name="name"></param>
        /// <param name="anew"></param>
        /// <param name="writable"></param>
        /// <returns></returns>
        private RegistryKey OpenSubKey(string name, bool anew, bool writable)
        {
            return anew ? MainKey.OpenSubKey(name, writable) : CurrentRegistryKey.OpenSubKey(name, writable);
        }

        /// <summary>
        /// 返回RegistryValueKind的数据类型
        /// </summary>
        /// <param name="regValueKind"></param>
        /// <returns></returns>
        private RegistryValueKind GetRegValueKind(RegValueKind regValueKind)
        {
            RegistryValueKind regValueK;
            switch (regValueKind)
            {
                case RegValueKind.Unknown:
                    regValueK = RegistryValueKind.Unknown; break;
                case RegValueKind.String:
                    regValueK = RegistryValueKind.String; break;
                case RegValueKind.ExpandString:
                    regValueK = RegistryValueKind.ExpandString; break;
                case RegValueKind.Binary:
                    regValueK = RegistryValueKind.Binary; break;
                case RegValueKind.DWord:
                    regValueK = RegistryValueKind.DWord; break;
                case RegValueKind.MultiString:
                    regValueK = RegistryValueKind.MultiString; break;
                case RegValueKind.QWord:
                    regValueK = RegistryValueKind.QWord; break;
                default:
                    regValueK = RegistryValueKind.String; break;
            }
            return regValueK;
        }

        /// <summary>
        /// 设置注册表基项域
        /// </summary>
        /// <param name="mainRegistryKey"></param>
        public void SetMainRegistryKey(MainRegistryKey mainRegistryKey)
        {
            switch (mainRegistryKey)
            {
                case MainRegistryKey.ClassesRoot:
                    MainKey = Registry.ClassesRoot; break;
                case MainRegistryKey.CurrentUser:
                    MainKey = Registry.CurrentUser; break;
                case MainRegistryKey.User:
                    MainKey = Registry.Users; break;
                case MainRegistryKey.CurrentConfig:
                    MainKey = Registry.CurrentConfig; break;
                case MainRegistryKey.DynDa:
                    MainKey = Registry.DynData; break;
                case MainRegistryKey.PerformanceData:
                    MainKey = Registry.PerformanceData; break;
                case MainRegistryKey.LocalMachine:
                default:
                    MainKey = Registry.LocalMachine; break;
            }
        }

        /// <summary>
        /// 设置当前注册表的路径
        /// </summary>
        /// <param name="name"></param>
        /// <param name="anew"></param>
        /// <param name="writable"></param>
        public void SetCurrentRegistryKey(string name, bool anew = false, bool writable = false)
        {
            CurrentRegistryKey = OpenSubKey(name, anew, writable);
        }

        /// <summary>
        /// 判断项是否存在，如果存在是否需要赋值至CurrentRegistryKey
        /// </summary>
        /// <param name="keyName"></param>
        /// <param name="anew"></param>
        /// <param name="isCopy">如果存在是否需要赋值至CurrentRegistryKey</param>
        /// <returns></returns>
        public bool IsExistKey(string keyName, bool anew = false, bool isCopy = false)
        {
            RegistryKey key = OpenSubKey(keyName, anew, false);
            if (key != null && isCopy)
            {
                CurrentRegistryKey = key;
            }
            return key != null;
        }

        /// <summary>
        /// 添加注册表中的项
        /// </summary>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public void AddRegisterKey(string key, string name = null, string value = null,RegValueKind regValueKind = RegValueKind.String)
        {
            RegistryKey subKey = CurrentRegistryKey.CreateSubKey(key);
            if (!string.IsNullOrEmpty(name))
            {
                SetValue(subKey, name, value, regValueKind);
            }
        }

        /// <summary>
        /// 删除注册表中的项
        /// </summary>
        /// <param name="subKey"></param>
        /// <returns></returns>
        public bool DelRegisterKey(string subKey)
        {
            bool result = false;
            try
            {
                CurrentRegistryKey.DeleteSubKeyTree(subKey);
                MainKey.Close();
                result = true;
            }
            catch (Exception)
            {

            }
            return result;
        }

        /// <summary>
        /// 判断值是否存在
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool IsExistName(string name)
        {
            bool result = false;
            foreach (string value in CurrentRegistryKey.GetValueNames())
            {
                if (value.ToLower() == name.ToLower())
                {
                    result = true;
                }
            }
            return result;
        }

        /// <summary>
        /// 设置注册表中的值
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public void SetRegisterKeyValue(string name, string value, RegValueKind regValueKind)
        {
            SetValue(CurrentRegistryKey, name, value, regValueKind);
        }

        /// <summary>
        /// 获取注册表中的值
        /// </summary>
        /// <param name="name"></param>
        public void GetRegisterKeyValue(string name)
        {
            RegistryKey subKey = CurrentRegistryKey.OpenSubKey(name);
            subKey.GetValue(name);
        }

        /// <summary>
        /// 删除注册表中的键值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool DelRegisterKeyValue(string key, string name)
        {
            bool result = false;
            RegistryKey subKey = CurrentRegistryKey.OpenSubKey(key);
            try
            {
                subKey.DeleteValue(name, true);
                MainKey.Close();
                result = true;
            }
            catch (Exception)
            {

            }
            return result;
        }

        /// <summary>
        /// 获取下级所有项的名称
        /// </summary>
        /// <returns></returns>
        public string[] GetSubRegisterKeyNames()
        {
            return CurrentRegistryKey.GetSubKeyNames();
        }

        /// <summary>
        /// 获取当前项所有值的名称
        /// </summary>
        /// <returns></returns>
        public string[] GetSubRegisterKeyValueNames()
        {
            return CurrentRegistryKey.GetValueNames();
        }
    }

    public enum MainRegistryKey
    {
        /// <summary>
        /// 对应于HKEY_CLASSES_ROOT主键
        /// </summary>
        ClassesRoot = 0,
        /// <summary>
        /// 对应于HKEY_CURRENT_USER主键
        /// </summary>
        CurrentUser = 1,
        /// <summary>
        /// 对应于 HKEY_LOCAL_MACHINE主键
        /// </summary>
        LocalMachine = 2,
        /// <summary>
        /// 对应于 HKEY_USER主键
        /// </summary>
        User = 3,
        /// <summary>
        /// 对应于HEKY_CURRENT_CONFIG主键
        /// </summary>
        CurrentConfig = 4,
        /// <summary>
        /// 对应于HKEY_DYN_DATA主键
        /// </summary>
        DynDa = 5,
        /// <summary>
        /// 对应于HKEY_PERFORMANCE_DATA主键
        /// </summary>
        PerformanceData = 6,
    }

    public enum RegValueKind
    {
        /// <summary>
        /// 指示一个不受支持的注册表数据类型。例如，不支持 Microsoft Win32 API 注册表数据类型 REG_RESOURCE_LIST。使用此值指定
        /// </summary>
        Unknown = 0,
        /// <summary>
        /// 指定一个以 Null 结尾的字符串。此值与 Win32 API 注册表数据类型 REG_SZ 等效。
        /// </summary>
        String = 1,
        /// <summary>
        /// 指定一个以 NULL 结尾的字符串，该字符串中包含对环境变量（如 %PATH%，当值被检索时，就会展开）的未展开的引用。
        /// 此值与 Win32 API注册表数据类型 REG_EXPAND_SZ 等效。
        /// </summary>
        ExpandString = 2,
        /// <summary>
        /// 指定任意格式的二进制数据。此值与 Win32 API 注册表数据类型 REG_BINARY 等效。
        /// </summary>
        Binary = 3,
        /// <summary>
        /// 指定一个 32 位二进制数。此值与 Win32 API 注册表数据类型 REG_DWORD 等效。
        /// </summary>
        DWord = 4,
        /// <summary>
        /// 指定一个以 NULL 结尾的字符串数组，以两个空字符结束。此值与 Win32 API 注册表数据类型 REG_MULTI_SZ 等效。
        /// </summary>
        MultiString = 5,
        /// <summary>
        /// 指定一个 64 位二进制数。此值与 Win32 API 注册表数据类型 REG_QWORD 等效。
        /// </summary>
        QWord = 6,
    }
}
